package com.sugar.real.estate.module.business.service.readyhouse;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sugar.real.estate.framework.common.pojo.PageResult;
import com.sugar.real.estate.framework.common.util.object.BeanUtils;
import com.sugar.real.estate.module.business.controller.admin.readyhouse.vo.ReadyHousePageReqVO;
import com.sugar.real.estate.module.business.controller.admin.readyhouse.vo.ReadyHouseRespVO;
import com.sugar.real.estate.module.business.controller.admin.readyhouse.vo.ReadyHouseSaveReqVO;
import com.sugar.real.estate.module.business.controller.app.info.vo.AppInfoRespVO;
import com.sugar.real.estate.module.business.controller.app.readyhouse.vo.AppReadyHouseDetailRespVO;
import com.sugar.real.estate.module.business.controller.app.readyhouse.vo.AppReadyHousePageReqVO;
import com.sugar.real.estate.module.business.controller.app.readyhouse.vo.AppReadyHouseSimpleRespVO;
import com.sugar.real.estate.module.business.dal.dataobject.dicttype.BizDictDataDO;
import com.sugar.real.estate.module.business.dal.dataobject.infohouse.InfoHouseDO;
import com.sugar.real.estate.module.business.dal.dataobject.openedcity.OpenedCityDO;
import com.sugar.real.estate.module.business.dal.dataobject.readyhouse.ReadyHouseDO;
import com.sugar.real.estate.module.business.dal.dataobject.userbuildingconsult.UserBuildingConsultDO;
import com.sugar.real.estate.module.business.dal.dataobject.userfollow.UserFollowDO;
import com.sugar.real.estate.module.business.dal.mysql.dicttype.BizDictDataMapper;
import com.sugar.real.estate.module.business.dal.mysql.infohouse.InfoHouseMapper;
import com.sugar.real.estate.module.business.dal.mysql.openedcity.OpenedCityMapper;
import com.sugar.real.estate.module.business.dal.mysql.readyhouse.ReadyHouseMapper;
import com.sugar.real.estate.module.business.dal.mysql.userbuildingconsult.UserBuildingConsultMapper;
import com.sugar.real.estate.module.business.dal.mysql.userfollow.UserFollowMapper;
import com.sugar.real.estate.module.business.service.dicttype.BizDictTypeService;
import com.sugar.real.estate.module.business.service.openedcity.OpenedCityService;
import com.sugar.real.estate.module.business.util.I18nUtil;
import com.sugar.real.estate.module.infra.controller.admin.file.vo.file.FileUploadReqVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.sugar.real.estate.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.real.estate.module.business.enums.ErrorCodeConstants.*;

/**
 * 现房 Service 实现类
 *
 * @author Ysugar
 */
@Slf4j
@Service
@Validated
public class ReadyHouseServiceImpl implements ReadyHouseService {

    @Resource
    private ReadyHouseMapper readyHouseMapper;
    @Resource
    private OpenedCityService openedCityService;
    @Resource
    private InfoHouseMapper infoHouseMapper;
    @Resource
    private UserFollowMapper userFollowMapper;
    @Resource
    private UserBuildingConsultMapper userBuildingConsultMapper;
    @Resource
    private BizDictTypeService dictTypeService;
    @Resource
    private BizDictDataMapper bizDictDataMapper;
    @Resource
    private OpenedCityMapper openedCityMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createReadyHouse(ReadyHouseSaveReqVO createReqVO) {
        Long[] locationIds = createReqVO.getLocationIds();
        if (Objects.nonNull(locationIds) && locationIds.length == 2) {
            createReqVO.setCityId(locationIds[0]);
            createReqVO.setCountyId(locationIds[1]);
        }else {
            throw exception(OPENED_CITY_NO_SELECT);
        }
        /*if (Objects.nonNull(locationIds) && locationIds.length > 0) {
            int length = locationIds.length;
            switch (length) {
                case 3:
                    createReqVO.setCountyId(locationIds[2]);
                case 2:
                    createReqVO.setCityId(locationIds[1]);
                case 1:
                    createReqVO.setProvinceId(locationIds[0]);
            }
        } else {
            // 尝试获取获取省市区ID
            String[] location = createReqVO.getLocation();
            if (Objects.nonNull(location)) {
                int length = location.length;
                if (length > 0) {
                    Long provinceId = openedCityService.getSameOpenedCity(location[0], 0L);
                    Long cityId = length >= 2 ? openedCityService.getSameOpenedCity(location[1], provinceId) : null;
                    Long countyId = length >= 3 ? openedCityService.getSameOpenedCity(location[2], cityId) : null;

                    createReqVO.setProvinceId(provinceId).setCityId(cityId).setCountyId(countyId);
                }
            }
        }*/

        // 插入
        ReadyHouseDO readyHouse = BeanUtils.toBean(createReqVO, ReadyHouseDO.class);
        readyHouseMapper.insert(readyHouse);
        Long houseId = readyHouse.getId();

        // 插入资讯关联信息
        Long[] infoIds = createReqVO.getInfoIds();
        if (null != infoIds) {
            for (Long infoId : infoIds) {
                if (infoId != null){
                    InfoHouseDO infoHouseDO = new InfoHouseDO().setType(true).setInfoId(infoId).setHouseId(houseId);
                    infoHouseMapper.insert(infoHouseDO);
                }
            }
        }

        // 返回
        return readyHouse.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateReadyHouse(ReadyHouseSaveReqVO updateReqVO) {
        // 校验存在
        Long houseId = updateReqVO.getId();
        validateReadyHouseExists(houseId);

        Long[] locationIds = updateReqVO.getLocationIds();
        if (Objects.nonNull(locationIds) && locationIds.length == 2) {
            updateReqVO.setCityId(locationIds[0]);
            updateReqVO.setCountyId(locationIds[1]);
        }else {
            throw exception(OPENED_CITY_NO_SELECT);
        }
        // 尝试获取获取省市区ID
        /*String[] location = updateReqVO.getLocation();
        if (Objects.nonNull(location)) {
            int length = location.length;
            if (length > 0) {
                Long provinceId = openedCityService.getSameOpenedCity(location[0], 0L);
                Long cityId = length >= 2 ? openedCityService.getSameOpenedCity(location[1], provinceId) : null;
                Long countyId = length >= 3 ? openedCityService.getSameOpenedCity(location[2], cityId) : null;

                updateReqVO.setProvinceId(provinceId).setCityId(cityId).setCountyId(countyId);
            }
        }else {
            Long[] locationIds = updateReqVO.getLocationIds();
            if (Objects.nonNull(locationIds) && locationIds.length > 0) {
                int length = locationIds.length;
                switch (length) {
                    case 3:
                        updateReqVO.setCountyId(locationIds[2]);
                    case 2:
                        updateReqVO.setCityId(locationIds[1]);
                    case 1:
                        updateReqVO.setProvinceId(locationIds[0]);
                }
            }
        }*/

        // 删除原来的资讯关联信息
        infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery().eq(InfoHouseDO::getType, 1).eq(InfoHouseDO::getHouseId, houseId));

        // 插入新的
        Long[] newInfoIds = updateReqVO.getInfoIds();
        if (null != newInfoIds) {
            for (Long newInfoId : newInfoIds) {
                if (newInfoId != null){
                    InfoHouseDO infoHouseDO = new InfoHouseDO().setType(true).setInfoId(newInfoId).setHouseId(houseId);
                    infoHouseMapper.insert(infoHouseDO);
                }
            }
        }

        // 更新
        ReadyHouseDO updateObj = BeanUtils.toBean(updateReqVO, ReadyHouseDO.class);
        readyHouseMapper.updateById(updateObj);
    }

    @Override
    public void deleteReadyHouse(Long id) {
        // 校验存在
        validateReadyHouseExists(id);
        // 删除
        readyHouseMapper.deleteById(id);
        // 删除资讯关联信息
        infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery()
                .eq(InfoHouseDO::getType, 1).eq(InfoHouseDO::getHouseId, id));
        // 删除用户关注
        userFollowMapper.delete(Wrappers.<UserFollowDO>lambdaQuery()
                .eq(UserFollowDO::getType, 1).eq(UserFollowDO::getFollowId, id));
        // 删除用户咨询
        userBuildingConsultMapper.delete(Wrappers.<UserBuildingConsultDO>lambdaQuery()
                .eq(UserBuildingConsultDO::getType, 1).eq(UserBuildingConsultDO::getFollowId, id));
    }

    @Override
    public void deleteReadyHouseListByIds(List<Long> ids) {
        // 校验存在
        validateReadyHouseExists(ids);
        // 删除
        readyHouseMapper.deleteByIds(ids);
        for (Long id : ids) {
            // 删除资讯关联信息
            infoHouseMapper.delete(Wrappers.<InfoHouseDO>lambdaQuery()
                    .eq(InfoHouseDO::getType, 1).eq(InfoHouseDO::getHouseId, id));
            // 删除用户关注
            userFollowMapper.delete(Wrappers.<UserFollowDO>lambdaQuery()
                    .eq(UserFollowDO::getType, 1).eq(UserFollowDO::getFollowId, id));
            // 删除用户咨询
            userBuildingConsultMapper.delete(Wrappers.<UserBuildingConsultDO>lambdaQuery()
                    .eq(UserBuildingConsultDO::getType, 1).eq(UserBuildingConsultDO::getFollowId, id));
        }
    }

    private void validateReadyHouseExists(List<Long> ids) {
        List<ReadyHouseDO> list = readyHouseMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(READY_HOUSE_NOT_EXISTS);
        }
    }

    private void validateReadyHouseExists(Long id) {
        if (readyHouseMapper.selectById(id) == null) {
            throw exception(READY_HOUSE_NOT_EXISTS);
        }
    }

    @Override
    public ReadyHouseRespVO getReadyHouse(Long id) {
        ReadyHouseDO readyHouseDO = readyHouseMapper.selectById(id);
        if (Objects.nonNull(readyHouseDO)) {
            ReadyHouseRespVO respVO = BeanUtils.toBean(readyHouseDO, ReadyHouseRespVO.class);
            List<Long> locationIds = new ArrayList<>();
            /*if (Objects.nonNull(readyHouseDO.getProvinceId()))
                locationIds.add(readyHouseDO.getProvinceId());*/
            if (Objects.nonNull(readyHouseDO.getCityId()))
                locationIds.add(readyHouseDO.getCityId());
            if (Objects.nonNull(readyHouseDO.getCountyId()))
                locationIds.add(readyHouseDO.getCountyId());

            List<InfoHouseDO> infoHouses = infoHouseMapper.selectList(Wrappers.<InfoHouseDO>lambdaQuery()
                    .eq(InfoHouseDO::getHouseId, readyHouseDO.getId())
                    .eq(InfoHouseDO::getType, 1));
            respVO.setLocationIds(locationIds)
                    .setInfoIds(infoHouses.stream().map(InfoHouseDO::getInfoId).collect(Collectors.toList()));
            return respVO;
        }
        return null;
    }

    @Override
    public PageResult<ReadyHouseRespVO> getReadyHousePage(ReadyHousePageReqVO pageReqVO) {
        PageResult<ReadyHouseRespVO> pageResult = readyHouseMapper.selectPage(pageReqVO);
        pageResult.getList().forEach(readyHouse -> {
            // 查询关注数
            readyHouse.setFollowCount(userFollowMapper.selectCount(UserFollowDO::getFollowId, readyHouse.getId(), UserFollowDO::getType, 1));
            // 查询咨询数
            readyHouse.setConsultCount(userBuildingConsultMapper.selectCount(UserBuildingConsultDO::getFollowId, readyHouse.getId(), UserBuildingConsultDO::getType, 1));
        });
        return pageResult;
    }

    @Override
    public PageResult<AppReadyHouseSimpleRespVO> appGetReadyHousePage(AppReadyHousePageReqVO reqVO) {
        Long countyId = reqVO.getCountyId();
        // 若名称不为空，则筛选地址有没有这个名称的
        if (StrUtil.isNotBlank(reqVO.getName())){
            if (countyId == null){
                String name = StrUtil.upperFirst(reqVO.getName());
                OpenedCityDO openedCityDO = openedCityMapper.selectOne(Wrappers.<OpenedCityDO>lambdaQuery().ne(OpenedCityDO::getParentId, 0)
                        .nested(o -> o.eq(OpenedCityDO::getNameEnUs, name).or().eq(OpenedCityDO::getNameZhCn, name))
                        .last("LIMIT 1"));
                if (openedCityDO != null){
                    reqVO.setCountyId(openedCityDO.getId());
                    reqVO.setName(null);
                }
            }
        }

        PageResult<ReadyHouseDO> pageResult = readyHouseMapper.appSelectPage(reqVO);
        boolean chinese = I18nUtil.isChinese();
        return BeanUtils.toBean(pageResult, AppReadyHouseSimpleRespVO.class,
                o -> o.setShowImage(o.getShowImages().get(0))
                        .setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setSalesMethod(chinese ? o.getSalesMethodZhCn() : o.getSalesMethodEnUs())
                        .setHouseTypeName(dictTypeService.appGetAllDictDataLabel(1L, o.getHouseType()))
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));
    }

    @Override
    public List<AppReadyHouseSimpleRespVO> getReadyHouseListByMap(AppReadyHousePageReqVO reqVO) {
        Long countyId = reqVO.getCountyId();
        // 若名称不为空，则筛选地址有没有这个名称的
        if (StrUtil.isNotBlank(reqVO.getName())){
            if (countyId == null){
                String name = StrUtil.upperFirst(reqVO.getName());
                OpenedCityDO openedCityDO = openedCityMapper.selectOne(Wrappers.<OpenedCityDO>lambdaQuery().ne(OpenedCityDO::getParentId, 0)
                        .nested(o -> o.eq(OpenedCityDO::getNameEnUs, name).or().eq(OpenedCityDO::getNameZhCn, name))
                        .last("LIMIT 1"));
                if (openedCityDO != null){
                    reqVO.setCountyId(openedCityDO.getId());
                    reqVO.setName(null);
                }
            }
        }

        boolean chinese = I18nUtil.isChinese();
        return BeanUtils.toBean(readyHouseMapper.appSelectPage(reqVO).getList(), AppReadyHouseSimpleRespVO.class,
                o -> o.setShowImage(o.getShowImages().get(0))
                        .setName(I18nUtil.getMessage(o, "getName"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));
    }

    @Override
    public AppReadyHouseDetailRespVO appGetReadyHouse(Long id, Long userId) {
        ReadyHouseDO readyHouseDO = readyHouseMapper.selectById(id);
        boolean chinese = I18nUtil.isChinese();

        AppReadyHouseDetailRespVO respVO = BeanUtils.toBean(readyHouseDO, AppReadyHouseDetailRespVO.class,
                o -> o.setName(I18nUtil.getMessage(o, "getName"))
                        .setContent(I18nUtil.getMessage(o, "getContent"))
                        .setTags(chinese ? o.getTagsZhCn() : o.getTagsEnUs())
                        .setHouseType(dictTypeService.appGetAllDictDataLabel(1L, o.getHouseType()))
                        .setProjectTypeName(dictTypeService.appGetAllDictDataLabel(2L, o.getProjectType())));

        // 获取资讯数量
        Long count = infoHouseMapper.selectCount(Wrappers.<InfoHouseDO>lambdaQuery()
                .eq(InfoHouseDO::getHouseId, id)
                .eq(InfoHouseDO::getType, 1));

        respVO.setHaveMoreInfo(count > 1);
        // 获取资讯
        if (count > 0){
            AppInfoRespVO appInfoRespVO = infoHouseMapper.selectListCustom(id, 1);
            appInfoRespVO.setTitle(I18nUtil.getMessage(appInfoRespVO, "getTitle"))
                    .setContent(I18nUtil.getMessage(appInfoRespVO, "getContent"))
                    .setAuthor(I18nUtil.getMessage(appInfoRespVO, "getAuthor"));
            respVO.setInfo(appInfoRespVO);
        }

        // 获取当前用户是否关注
        if (Objects.nonNull(userId)){
            Long isUserFollow = userFollowMapper.selectCount(Wrappers.<UserFollowDO>lambdaQuery()
                    .eq(UserFollowDO::getUserId, userId)
                    .eq(UserFollowDO::getType, 1)
                    .eq(UserFollowDO::getFollowId, id));
            respVO.setUserFollow(isUserFollow > 0);
        }

        // 更新查看数量
        readyHouseMapper.update(ReadyHouseDO::getId, readyHouseDO.getId(), ReadyHouseDO::getLookCount, readyHouseDO.getLookCount() + 1);

        return respVO;
    }

    @Override
    public void importExcel(FileUploadReqVO uploadReqVO) {
        final int[] i = {2};

        try {
            EasyExcel.read(uploadReqVO.getFile().getInputStream(), new ReadListener<Map<Integer, String>>() {
                @Override
                public void invoke(Map<Integer, String> data, AnalysisContext context) {
                    try {
                        ReadyHouseDO readyHouse = new ReadyHouseDO();
                        readyHouse.setNameZhCn(data.get(0));
                        readyHouse.setNameEnUs(data.get(1));
                        readyHouse.setShowImages(Arrays.stream(data.get(2).split(",")).collect(Collectors.toList()));
                        String data3 = data.get(3);
                        if (StrUtil.isNotBlank(data3))
                            readyHouse.setShowVideos(Arrays.stream(data3.split(",")).collect(Collectors.toList()));
                        String data4 = data.get(4);
                        if (StrUtil.isNotBlank(data4))
                            readyHouse.setShowImagesHouseType(Arrays.stream(data4.split(",")).collect(Collectors.toList()));
                        BizDictDataDO bizDictDataDO = bizDictDataMapper.selectOne(Wrappers.<BizDictDataDO>lambdaQuery().eq(BizDictDataDO::getDictTypeId, 1)
                                .nested(w -> w.eq(BizDictDataDO::getLabelEnUs, data.get(5))
                                        .or().eq(BizDictDataDO::getLabelZhCn, data.get(5))));
                        if (bizDictDataDO != null)
                            readyHouse.setHouseType(bizDictDataDO.getValue());

                        String data6 = data.get(6);
                        if (StrUtil.isNotBlank(data6))
                            readyHouse.setPriceMin(new BigDecimal(data6));
                        String data7 = data.get(7);
                        if (StrUtil.isNotBlank(data7))
                            readyHouse.setIsShowPrice("是".equals(data7));
                        String data8 = data.get(8);
                        if (StrUtil.isNotBlank(data8))
                            readyHouse.setTagsZhCn(Arrays.stream(data8.split(",")).collect(Collectors.toList()));
                        String data9 = data.get(9);
                        if (StrUtil.isNotBlank(data9))
                            readyHouse.setTagsEnUs(Arrays.stream(data9.split(",")).collect(Collectors.toList()));
                        BizDictDataDO bizDictDataDO2 = bizDictDataMapper.selectOne(Wrappers.<BizDictDataDO>lambdaQuery().eq(BizDictDataDO::getDictTypeId, 2)
                                .nested(w -> w.eq(BizDictDataDO::getLabelEnUs, data.get(10))
                                        .or().eq(BizDictDataDO::getLabelZhCn, data.get(10))));
                        if (bizDictDataDO2 != null)
                            readyHouse.setProjectType(bizDictDataDO2.getValue());
                        readyHouse.setSalesMethodZhCn(data.get(11));
                        readyHouse.setSalesMethodEnUs(data.get(12));
                        readyHouse.setHouseArea(new BigDecimal(data.get(13)));
                        readyHouse.setContentZhCn(data.get(14));
                        readyHouse.setContentEnUs(data.get(15));
                        readyHouse.setPoint(data.get(16));
                        readyHouse.setPointDetail(data.get(17));
                        readyHouse.setLandArea(data.get(18));
                        readyHouse.setBedroomCount(data.get(19));
                        readyHouse.setBathroom(data.get(20));
                        readyHouse.setLivingRoom(data.get(21));

                        // 插入
                        readyHouseMapper.insert(readyHouse);
                        i[0] = i[0] + 1;
                    }catch (Throwable e){
                        log.error("导入现房数据失败：", e);
                        throw exception(SERVER_BUSY);
                    }
                }

                // 读取完毕
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                }
            }).sheet().doRead();
        }catch (Throwable e){
            throw exception(IMPORT_EXCEL_ERROR, i[0]);
        }
    }

    @Override
    public void updateReadyHouseStatus(Long id, Boolean isShow) {
        readyHouseMapper.update(ReadyHouseDO::getId, id, ReadyHouseDO::getIsShow, isShow);
    }

}